﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using System.Linq.Expressions;

namespace DongFangGuoKai.WMSPlatform.Core.Repository
{
    public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
    {

        private readonly WMSPlatformContext _context;

        public Repository(WMSPlatformContext context)
        {
            _context = context;
        }

        #region Get   
        public List<TEntity> GetList()
        {
            return _context.Set<TEntity>().ToList();
        }
        public List<TEntity> GetList(Expression<Func<TEntity, bool>> predicate)
        {
            return _context.Set<TEntity>().Where(predicate).ToList();
        }
        public List<TEntity> GetList(Expression<Func<TEntity, bool>> predicate, string sort, int pageIndex, int pageSize, bool isAsc = true)
        {
            int skip = (pageIndex - 1) * pageSize;
            var dbSet = _context.Set<TEntity>();
            return isAsc ? dbSet.Where(predicate).OrderBy(m => sort).Skip(skip).Take(pageSize).ToList()
                         : dbSet.Where(predicate).OrderByDescending(m => sort).Skip(skip).Take(pageSize).ToList();
        }
        public List<TEntity> GetList(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, object>> sort, int pageIndex, int pageSize, bool isAsc = true)
        {
            int skip = (pageIndex - 1) * pageSize;
            var dbSet = _context.Set<TEntity>();
            return isAsc ? dbSet.Where(predicate).OrderBy(sort).Skip(skip).Take(pageSize).ToList()
                         : dbSet.Where(predicate).OrderByDescending(sort).Skip(skip).Take(pageSize).ToList();
        }
        public List<TEntity> GetList(string sort, int pageIndex, int pageSize, bool isAsc = true)
        {
            int skip = (pageIndex - 1) * pageSize;
            var dbSet = _context.Set<TEntity>();
            return isAsc ? dbSet.OrderBy(m => sort).Skip(skip).Take(pageSize).ToList()
                         : dbSet.OrderByDescending(m => sort).Skip(skip).Take(pageSize).ToList();
        }


        public async Task<List<TEntity>> GetListAsync()
        {
            return await _context.Set<TEntity>().ToListAsync();
        }
        public async Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate)
        {
            return await _context.Set<TEntity>().Where(predicate).ToListAsync();
        }
        public async Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate, string sort, int pageIndex, int pageSize, bool isAsc = true)
        {
            int skip = (pageIndex - 1) * pageSize;
            var dbSet = _context.Set<TEntity>();
            return await (isAsc ? dbSet.Where(predicate).OrderBy(m => sort).Skip(skip).Take(pageSize).ToListAsync()
                         : dbSet.Where(predicate).OrderByDescending(m => sort).Skip(skip).Take(pageSize).ToListAsync());
        }
        public async Task<List<TEntity>> GetListAsync(string sort, int pageIndex, int pageSize, bool isAsc = true)
        {
            int skip = (pageIndex - 1) * pageSize;
            var dbSet = _context.Set<TEntity>();
            return await (isAsc ? dbSet.OrderBy(m => sort).Skip(skip).Take(pageSize).ToListAsync()
                         : dbSet.OrderByDescending(m => sort).Skip(skip).Take(pageSize).ToListAsync());
        }
        public async Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, object>> sort, int pageIndex, int pageSize, bool isAsc = true)
        {
            int skip = (pageIndex - 1) * pageSize;
            var dbSet = _context.Set<TEntity>();
            return await (isAsc ? dbSet.Where(predicate).OrderBy(sort).Skip(skip).Take(pageSize).ToListAsync()
                         : dbSet.Where(predicate).OrderByDescending(sort).Skip(skip).Take(pageSize).ToListAsync());
        }

        public TEntity Get(Expression<Func<TEntity, bool>> predicate)
        {
            var dbSet = _context.Set<TEntity>();
            return dbSet.FirstOrDefault(predicate);
        }

        public async Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate)
        {
            var dbSet = _context.Set<TEntity>();
            return await dbSet.FirstOrDefaultAsync(predicate);
        }

        public IQueryable<TEntity> GetQueryable()
        {
            var dbSet = _context.Set<TEntity>();
            return dbSet;
        }
        #endregion

        #region  Insert 
        public TEntity Insert(TEntity entity)
        {
            var dbSet = _context.Set<TEntity>();
            TEntity t = dbSet.Add(entity).Entity;
            _context.SaveChanges();
            return t;
        }

        public async Task<TEntity> InsertAsync(TEntity entity)
        {
            var dbSet = _context.Set<TEntity>();
            TEntity t = (await dbSet.AddAsync(entity)).Entity;
            await _context.SaveChangesAsync();
            return t;
        }

        public List<TEntity> InsertRange(List<TEntity> entities)
        {
            var dbSet = _context.Set<TEntity>();
            dbSet.AddRange(entities);
            _context.SaveChanges();
            return entities;
        }

        #endregion

        #region Update
        public bool Update(TEntity entity)
        {
            var dbSet = _context.Set<TEntity>();

            dbSet.Update(entity);
            _context.SaveChanges();
            return true;
        }

        public async Task<bool> UpdateAsync(TEntity entity)
        {
            var dbSet = _context.Set<TEntity>();
            dbSet.Update(entity);
            await _context.SaveChangesAsync();
            return true;
        }

        public bool TryUpdateModel(TEntity tEntity, params string[] updateFiled)
        { 
            var entry = _context.Entry<TEntity>(tEntity);
            entry.State = EntityState.Detached;
            foreach (var item in updateFiled)
            {
                entry.Property(item).IsModified = true;
            }
            _context.SaveChanges();
            return true;
        }
        #endregion

        #region Delete  
        public bool Delete(TEntity entity)
        {
            var dbSet = _context.Set<TEntity>();
            dbSet.Remove(entity);
            _context.SaveChanges();
            return true;
        }

        public bool Delete(Expression<Func<TEntity, bool>> predicate)
        {
            var dbSet = _context.Set<TEntity>();
            var list = dbSet.FirstOrDefault(predicate);
            if (list != null)
            {
                dbSet.Remove(list);
                _context.SaveChanges();
                return true;
            }
            return false;
        }
        public async Task<bool> DeleteAsync(TEntity entity)
        {
            var dbSet = _context.Set<TEntity>();
            dbSet.Remove(entity);
            await _context.SaveChangesAsync();
            return true;
        }

        public bool DeleteRange(IEnumerable<TEntity> entities)
        {

            _context.Set<TEntity>().RemoveRange(entities);
            _context.SaveChanges();
            return true;
        }
        #endregion


        #region 聚合  

        public int Count(Expression<Func<TEntity, bool>> predicate)
        {
            return _context.Set<TEntity>().Count(predicate);
        }

        public async Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate)
        {
            return await _context.Set<TEntity>().CountAsync(predicate);
        }

        public bool Any(Expression<Func<TEntity, bool>> predicate)
        {
            return _context.Set<TEntity>().Any(predicate);
        }

        #endregion


        public WMSPlatformContext GetContext()
        {
            return _context;
        }

    }
}
